跳到主要内容

IAT 挂钩导入表注入介绍

挂钩导入表(IAT Hooking)是一种通过修改可执行文件或动态链接库(DLL)的导入地址表(Import Address Table,IAT)来劫持函数调用的技术。IAT 是 PE(Portable Executable)文件格式的一部分,用于存储从外部模块(DLL)导入的函数地址。通过修改 IAT 中的地址,可以使程序调用的外部函数被替换为我们自己定义的函数。

原理

  1. 加载模块:当一个可执行文件(EXE)或 DLL 被加载时,Windows 加载器会解析它的 IAT,将表中的每个入口初始化为对应的导入函数的实际地址。

  2. 找到 IAT:首先,需要找到目标模块的 IAT。IAT 位于 PE 文件的 Data Directory 中,具体位置在 PE 头的 Data Directory 表中可以找到。

  3. 备份原始地址:在修改 IAT 之前,通常会备份原始的函数地址,以便在需要时恢复或在新函数中调用原始函数。

  4. 修改 IAT:将 IAT 中的目标函数地址修改为我们自己的函数地址。这样,当程序调用该函数时,会执行我们自定义的函数。

具体步骤

  1. 获取模块句柄:使用 GetModuleHandle 获取目标模块的句柄。

  2. 解析 PE 头:获取模块的 DOS 头、NT 头和导入表地址。

  3. 找到 IAT:从 PE 头的 Data Directory 表中找到导入表的位置和大小。

  4. 修改 IAT:遍历导入表,找到需要挂钩的函数地址,并将其替换为我们自定义的函数地址。

示例代码

下面是一个简单的示例代码,用于演示如何实现 IAT Hooking。这个示例代码将目标函数 MessageBoxA 替换为自定义的函数。

#include <windows.h>
#include <stdio.h>

// 原始的 MessageBoxA 函数指针
typedef int (WINAPI* pMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
pMessageBoxA OriginalMessageBoxA = NULL;

// 自定义的 MessageBoxA 函数
int WINAPI HookedMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
return OriginalMessageBoxA(hWnd, "Hooked!", lpCaption, uType);
}

void HookIAT() {
// 获取模块句柄
HMODULE hModule = GetModuleHandle(NULL);
if (hModule == NULL) return;

// 获取 DOS 头
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;

// 获取 NT 头
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + pDosHeader->e_lfanew);

// 获取导入表
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE*)hModule + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

// 遍历导入表
while (pImportDesc->Name) {
LPCSTR pszModName = (LPCSTR)((BYTE*)hModule + pImportDesc->Name);
if (_stricmp(pszModName, "user32.dll") == 0) {
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((BYTE*)hModule + pImportDesc->FirstThunk);
while (pThunk->u1.Function) {
PROC* ppfn = (PROC*)&pThunk->u1.Function;
if (*ppfn == (PROC)GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxA")) {
// 备份原始的函数地址
OriginalMessageBoxA = (pMessageBoxA)*ppfn;

// 修改 IAT
DWORD dwOldProtect;
VirtualProtect(ppfn, sizeof(PROC), PAGE_EXECUTE_READWRITE, &dwOldProtect);
*ppfn = (PROC)HookedMessageBoxA;
VirtualProtect(ppfn, sizeof(PROC), dwOldProtect, &dwOldProtect);
break;
}
pThunk++;
}
}
pImportDesc++;
}
}

int main() {
HookIAT();
MessageBoxA(NULL, "Original", "IAT Hooking", MB_OK);
return 0;
}